
package hk.ces.oxfam.patch.result.xml;

import hk.ces.oxfam.patch.config.Config;
import hk.ces.oxfam.patch.obj.DataDict;
import hk.ces.oxfam.patch.obj.FieldInfo;
import hk.ces.oxfam.patch.obj.TableInfo;
import hk.ces.oxfam.patch.xml.factory.PredefinedDataDict;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

/**
 *
 * @author ReutyCheng
 */
public final class DataDictXMLFactory extends AbstractXMLFactory<DataDict>
{
  private static final String NODE_DATA_DICT = "DataDict";
  private static final String NODE_TABLE = "Table";
  private static final String NODE_FIELD = "Field";
  private static final String NODE_RELATED_TABLE = "RelatedTable";
  private static final String ATTR_DATA_DICT_SERVER = "server";
  private static final String ATTR_TABLE_NAME = "name";
  private static final String ATTR_TABLE_DISC = "disc";
  private static final String ATTR_FIELD_NAME = "name";
  private static final String ATTR_FIELD_TYPE = "type";
  private static final String ATTR_FIELD_DISC = "disc";
  private static final String ATTR_FIELD_SIZE = "size";
  private static final String ATTR_TABLE_STATUS = "status";
  private static final String ATTR_FIELD_STATUS = "status";
  private static final String ATTR_RELATED_TABLE_NAME = "name";

  private static final String STATUS_UNDEFINED = "undefined";
  private static final String STATUS_DEFINED = "defined";

  public DataDictXMLFactory(String fileName)
  {
    super(fileName);
  }

  public DataDictXMLFactory(String folder, String fileName)
  {
    super(folder, fileName);
  }

  @Override
  protected Document getDocument()
  {
    Document document = addXMLStyleSheet(DocumentHelper.createDocument());
    Element dataDictRootElement = document.addElement(NODE_DATA_DICT);
    dataDictRootElement.addAttribute(ATTR_DATA_DICT_SERVER, Config.getCurrentConfigServer() + "");

    List<DataDict> dataDicts = this.xmlItemList;
    for (DataDict dataDict : dataDicts)
    {
      List<TableInfo> tableInfos = dataDict.getTableInfos();
      for (TableInfo tableInfo : tableInfos)
      {
        this.addTableNode(dataDictRootElement, tableInfo);
      }
    }

    return document;
  }

  @Override
  protected String getXslFileName()
  {
    return "data-dict-style.xsl";
  }

  private Element addTableNode(Element dataDictRootElement, TableInfo tableInfo)
  {
    String tableName = tableInfo.getTableName();
    if (PredefinedDataDict.get().isTableExcluded(tableName))
    {
      return dataDictRootElement;
    }

    Element tableInfoElement = dataDictRootElement.addElement(NODE_TABLE);

    String tableDisc = PredefinedDataDict.get().getTableDisc(tableName);
    tableInfoElement.addAttribute(ATTR_TABLE_NAME, tableInfo.getTableName());
    tableInfoElement.addAttribute(ATTR_TABLE_DISC, tableDisc != null ? tableDisc : "");
    tableInfoElement.addAttribute(ATTR_TABLE_STATUS, PredefinedDataDict.get().isTablePredefined(tableName) ? STATUS_DEFINED : STATUS_UNDEFINED);

    List<FieldInfo> fieldInfos = tableInfo.getInfoses();
    for (FieldInfo fieldInfo : fieldInfos)
    {
      String fieldName = fieldInfo.getColumnName();
      boolean fieldExclude = PredefinedDataDict.get().isFieldExclude(tableName, fieldName);
      if (!fieldExclude)
      {
        String fieldDisc = PredefinedDataDict.get().getFieldDisc(tableName, fieldName);

        Element fieldInfoElement = tableInfoElement.addElement(NODE_FIELD);
        fieldInfoElement.addAttribute(ATTR_FIELD_NAME, fieldInfo.getColumnName());
        fieldInfoElement.addAttribute(ATTR_FIELD_TYPE, fieldInfo.getTypeName());
        fieldInfoElement.addAttribute(ATTR_FIELD_SIZE, fieldInfo.getSize());
        fieldInfoElement.addAttribute(ATTR_FIELD_DISC, fieldDisc != null ? fieldDisc : "");
        fieldInfoElement.addAttribute(ATTR_FIELD_STATUS, PredefinedDataDict.get().isFieldPredefined(tableName, fieldName) ? STATUS_DEFINED : STATUS_UNDEFINED);
      }
    }

    List<String> relatedTables = PredefinedDataDict.get().getRelatedTables(tableName);
    for (String relatedTable : relatedTables)
    {
      Element relatedTableElement = tableInfoElement.addElement(NODE_RELATED_TABLE);
      relatedTableElement.addAttribute(ATTR_RELATED_TABLE_NAME, relatedTable);
    }

    return dataDictRootElement;
  }
}
